package com.willren;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.willren.WifiManagerEx.WifiApStateInterface.WifuApStateType;

import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;

/**
 * Hided method about WIFI AP
 * 
 * public android.net.wifi.WifiConfiguration
 * android.net.wifi.WifiManager.getWifiApConfiguration() public int
 * android.net.wifi.WifiManager.getWifiApState() public boolean
 * android.net.wifi.WifiManager.isWifiApEnabled() public int
 * android.net.wifi.WifiManager
 * .setWifiApConfig(android.net.wifi.WifiConfiguration) public boolean
 * android.net
 * .wifi.WifiManager.setWifiApEnabled(android.net.wifi.WifiConfiguration
 * ,boolean) public int
 * android.net.wifi.WifiManager.setWifiApMacList(android.net
 * .wifi.WifiConfiguration)
 * 
 */

public class WifiManagerEx {
	public static final long START_AP_TIMEOUT_SECONDS = 20;

	private static WifiManagerEx objWifiManagerEx = null;

	private WifiManager objWifiManager;

	private Method mthSetWifiApEnabled;
	private Method mthIsWifiApEnabled;
	private Method mthSetWifiApConfiguration;
	private Method mthGetWifiApConfiguration;

	WifiConfiguration wifiConfiguration;

	public interface WifiApStateInterface {
		public enum WifuApStateType {
			ApState_Started, ApState_Stoped, ApState_Error
		}

		public void wifiApStateChanged(WifuApStateType state);
	}

	public static WifiManagerEx getWifiManagerExInstance(Context context) {
		if (null == objWifiManagerEx) {
			objWifiManagerEx = new WifiManagerEx(context);
		}

		return objWifiManagerEx;
	}

	private WifiManagerEx(Context context) {
		objWifiManager = (WifiManager) context
				.getSystemService(Context.WIFI_SERVICE);

		mthSetWifiApEnabled = null;
		mthIsWifiApEnabled = null;
		mthSetWifiApConfiguration = null;
		mthGetWifiApConfiguration = null;

		initialize();
	}

	private void initialize() {
		Class<?> clsWifiManager = null;

		if (null != objWifiManager) {
			clsWifiManager = objWifiManager.getClass();
			Method ms[] = clsWifiManager.getMethods();
			for (Method m : ms) {
				if (-1 != m.toString().indexOf("setWifiApEn")) {
					mthSetWifiApEnabled = m;
				}

				if (-1 != m.toString().indexOf("isWifiApEn")) {
					mthIsWifiApEnabled = m;
				}

				if (-1 != m.toString().indexOf("setWifiApConfig")) {
					mthSetWifiApConfiguration = m;
				}

				if (-1 != m.toString().indexOf("getWifiApConfig")) {
					mthGetWifiApConfiguration = m;
				}
			}
		}

		try {
			if (null != mthGetWifiApConfiguration) {
				wifiConfiguration = ((WifiConfiguration) mthGetWifiApConfiguration
						.invoke(objWifiManager));
				if (null != wifiConfiguration) {
					wifiConfiguration.allowedKeyManagement.clear();
					wifiConfiguration.allowedKeyManagement
							.set(WifiConfiguration.KeyMgmt.NONE);
				}
			}
		} catch (IllegalArgumentException e) {
		} catch (IllegalAccessException e) {
		} catch (InvocationTargetException e) {
		}

		if (null == wifiConfiguration) {
			wifiConfiguration = new WifiConfiguration();
			if (null != wifiConfiguration) {
				wifiConfiguration.SSID = "Media Server";
				wifiConfiguration.allowedKeyManagement.clear();
				wifiConfiguration.allowedKeyManagement
						.set(WifiConfiguration.KeyMgmt.NONE);
			}
		}
	}

	private boolean saveWifiConfiguration(WifiConfiguration config) {
		boolean ret = false;

		if (null != mthSetWifiApConfiguration) {
			try {
				mthSetWifiApConfiguration.invoke(objWifiManager, config);

				ret = true;
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			} catch (InvocationTargetException e) {
			}
		}

		return ret;
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();

		if (null != wifiConfiguration) {
			sb.append("SSID: " + wifiConfiguration.SSID + "\n");
			sb.append("KEY: " + wifiConfiguration.preSharedKey + "\n");
			sb.append("KEY: " + wifiConfiguration.allowedAuthAlgorithms + "\n");
			sb.append("KEY: " + wifiConfiguration.allowedGroupCiphers + "\n");
			sb.append("KEY: " + wifiConfiguration.allowedKeyManagement + "\n");
			sb
					.append("KEY: " + wifiConfiguration.allowedPairwiseCiphers
							+ "\n");
			sb.append("KEY: " + wifiConfiguration.allowedProtocols + "\n");

			return sb.toString();
		}

		return "";
	}

	public String getApName() {
		if (null != wifiConfiguration) {
			return wifiConfiguration.SSID;
		}

		return null;
	}

	public boolean setApName(String apName) {
		boolean ret = false;

		if (null != wifiConfiguration) {
			if (null != apName && apName.trim().length() > 0) {
				wifiConfiguration.SSID = apName.trim();

				ret = saveWifiConfiguration(wifiConfiguration);
			}
		}

		return ret;
	}

	public boolean isEncrypted() {
		boolean ret = false;

		if (null != wifiConfiguration) {
			if (wifiConfiguration.allowedKeyManagement
					.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
				ret = true;
			}

			if (wifiConfiguration.allowedKeyManagement
					.get(WifiConfiguration.KeyMgmt.NONE)) {
				ret = false;
			}
		}

		return ret;
	}

	public boolean setEncrypted(boolean isEncrypted) {
		boolean ret = false;

		if (null != wifiConfiguration) {
			wifiConfiguration.allowedKeyManagement.clear();

			if (isEncrypted) {
				wifiConfiguration.allowedKeyManagement
						.set(WifiConfiguration.KeyMgmt.WPA_PSK);
			} else {
				wifiConfiguration.allowedKeyManagement
						.set(WifiConfiguration.KeyMgmt.NONE);
			}

			ret = saveWifiConfiguration(wifiConfiguration);
		}

		return ret;
	}

	public String getWepKey() {
		if (null != wifiConfiguration) {
			return wifiConfiguration.preSharedKey;
		}

		return null;
	}

	public boolean setWepKey(String wepKey) {
		boolean ret = false;

		if (null != wepKey && wepKey.trim().length() > 0) {
			if (null != wifiConfiguration) {
				wifiConfiguration.preSharedKey = wepKey.trim();

				ret = saveWifiConfiguration(wifiConfiguration);
			}
		}

		return ret;
	}

	public void startWifiAp(WifiApStateInterface callback) {
		final WifiApStateInterface finalCallback = callback;

		if (null != objWifiManager && null != mthSetWifiApEnabled
				&& null != wifiConfiguration) {
			try {
				mthSetWifiApEnabled.invoke(objWifiManager, wifiConfiguration,
						true);

				new Thread(new Runnable() {
					@Override
					public void run() {
						boolean isApEnable = false;
						long startTime = System.currentTimeMillis();
						while (false == isApEnable
								&& System.currentTimeMillis() - startTime < START_AP_TIMEOUT_SECONDS * 1000) {

							try {
								if (null != mthIsWifiApEnabled) {
									isApEnable = ((Boolean) mthIsWifiApEnabled
											.invoke(objWifiManager))
											.booleanValue();
								}

								Thread.sleep(1000);
							} catch (InterruptedException e) {

							} catch (InvocationTargetException e) {

							} catch (IllegalAccessException e) {

							}
						}

						if (null != finalCallback) {
							if (isApEnable) {
								finalCallback
										.wifiApStateChanged(WifuApStateType.ApState_Started);
							} else {
								finalCallback
										.wifiApStateChanged(WifuApStateType.ApState_Stoped);
							}
						}
					}
				}).start();
			} catch (InvocationTargetException e) {

			} catch (IllegalAccessException e) {

			}
		}
	}

	public void stopWifiAp(WifiApStateInterface callback) {
		final WifiApStateInterface finalCallback = callback;

		if (null != objWifiManager && null != mthSetWifiApEnabled
				&& null != wifiConfiguration) {
			try {
				mthSetWifiApEnabled.invoke(objWifiManager, wifiConfiguration,
						false);

				new Thread(new Runnable() {
					@Override
					public void run() {
						boolean isApEnable = false;
						long startTime = System.currentTimeMillis();
						while (true == isApEnable
								&& System.currentTimeMillis() - startTime < START_AP_TIMEOUT_SECONDS * 1000) {

							try {
								if (null != mthIsWifiApEnabled) {
									isApEnable = ((Boolean) mthIsWifiApEnabled
											.invoke(objWifiManager))
											.booleanValue();
								}

								Thread.sleep(1000);
							} catch (InterruptedException e) {

							} catch (InvocationTargetException e) {

							} catch (IllegalAccessException e) {

							}
						}

						if (null != finalCallback) {
							if (isApEnable) {
								finalCallback
										.wifiApStateChanged(WifuApStateType.ApState_Started);
							} else {
								finalCallback
										.wifiApStateChanged(WifuApStateType.ApState_Stoped);
							}
						}
					}
				}).start();
			} catch (InvocationTargetException e) {

			} catch (IllegalAccessException e) {

			}
		}
	}

	public boolean isWifiApStarted() {
		boolean isApEnable = false;

		if (null != objWifiManager && null != mthIsWifiApEnabled
				&& null != wifiConfiguration) {
			try {
				isApEnable = ((Boolean) mthIsWifiApEnabled
						.invoke(objWifiManager)).booleanValue();
			} catch (InvocationTargetException e) {

			} catch (IllegalAccessException e) {

			}
		}

		return isApEnable;
	}
}
